<template>
  <g-page class="page-chat">
    <div class="chat-header">
      <div class="chat-name">{{ chatStore.currentChat.model }} - {{ chatStore.currentChat.name }}</div>
    </div>
    <div class="chat-main">
      <t-chat ref="chatRef" layout="both" :clear-history="contentList.length > 0 && !streamLoading" @clear="onClear">
        <template v-for="(item, index) in contentList" :key="index">
          <t-chat-item :avatar="item.avatar" :name="item.name" :role="item.role" :datetime="item.datetime" :content="item.content" :text-loading="index === 0 && loading">
            <template v-if="!streamLoading" #actions>
              <t-chat-action :is-good="item.isGood" :is-bad="item.isBad" :content="item.content" @operation="handleOperation($event, index)" />
            </template>
            <template #content>
              <t-chat-reasoning v-if="item.reasoning?.length > 0" expand-icon-placement="right">
                <template #header>
                  <t-chat-loading v-if="item.thinking" text="思考中..." />
                  <div class="thinked" v-else>
                    <CheckCircleIcon />已深度思考
                  </div>
                </template>
                <t-chat-content :content="item.reasoning" />
              </t-chat-reasoning>
              <t-chat-content :content="item.content" />
            </template>
          </t-chat-item>
        </template>
        <t-chat-item v-if="chatStore.currentChat.prompt" :avatar="promptItem.avatar" :name="promptItem.name" :role="promptItem.role" :datetime="promptItem.datetime" :content="chatStore.currentChat.prompt" />
        <t-empty v-if="!chatStore.currentChat.prompt && !contentList.length" />
      </t-chat>
    </div>
    <div class="chat-footer">
      <t-chat-input placeholder="神棍说，要有光" :autofocus="!!chatStore.currentChat.model" :stop-disabled="streamLoading" @send="onSend" @stop="onStop" @focus="onFocus"> </t-chat-input>
    </div>
  </g-page>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { CheckCircleIcon } from 'tdesign-icons-vue-next';
import userImg from '@/assets/img/user.jpg'
import assistantImg from '@/assets/img/assistant.jpg'
import { chat, abort } from '@/chat/api'
import { useChatStore } from '@/chat/store'
import { MessagePlugin } from 'tdesign-vue-next';
import database from '@/indexedDB/Database';
import emitter from "@/utils/emitter";

const chatStore = useChatStore()
const loading = ref(false)
const streamLoading = ref(false)
const chatRef = ref(null)

function createChat(role: string, content = '') {
  if (role === 'assistant') {
    return {
      role: 'assistant',
      avatar: assistantImg,
      name: '助手',
      datetime: new Date().toLocaleString(),
      content: content,
      isGood: false,
      isBad: false,
      chatId: chatStore.currentChatId,
      thinking: true,
      reasoning: '',
    }
  } else if (role === 'user') {
    return {
      role: 'user',
      avatar: userImg,
      name: '自己',
      datetime: new Date().toLocaleString(),
      content: content,
      chatId: chatStore.currentChatId,
    }
  }
}

// 倒序渲染
const promptItem: any = createChat('assistant')
const contentList = ref<any>([])

watch(() => chatStore.currentChatId, (val: string) => {
  onStop()
  if (!val) {
    contentList.value = []
  } else {
    database.queryData('contents', 'chatId', val).then((res: any) => {
      contentList.value = res.reverse()
    })
  }
}, { immediate: true })

function onClear() {
  contentList.value = []
  database.deleteBatch('contents', (item: any) => item.chatId === chatStore.currentChatId).then(() => {
    MessagePlugin.success('清空成功')
  })
}

function onStop() {
  loading.value = false
  streamLoading.value = false
  abort()
}

function handleOperation(type: string, index: number) {
  const item: any = contentList.value[index]
  if (type === 'good') {
    item.isGood = !item.isGood
    item.isBad = false
  } else if (type === 'bad') {
    item.isBad = !item.isBad
    item.isGood = false
  } else if (type === 'replay') {
    onSend(contentList.value[index + 1].content)
  }
}

function onSend(val: string) {
  if (streamLoading.value || !val) {
    return
  }

  contentList.value.unshift(createChat('user', val))
  contentList.value.unshift(createChat('assistant', ''))

  loading.value = true
  streamLoading.value = true
  const isDeepseek = chatStore.currentChat.model.includes('deepseek')
  chat(val).then(async (stream: any) => {
    loading.value = false
    for await (const part of stream) {
      const content = part.message.content
      if (isDeepseek) {
        // thinking
        if (part.message.content === "\u003cthink\u003e") {
          contentList.value[0].thinking = true
        }
        if (contentList.value[0].thinking) {
          if (content !== "\u003cthink\u003e" && content !== "\u003c/think\u003e") {
            if (contentList.value[0].reasoning === '' && content === '\n\n') {
              // 丢掉空think
            } else {
              contentList.value[0].reasoning += content
            }
          }
          if (content == "\u003c/think\u003e") {
            contentList.value[0].thinking = false
          }
        } else {
          contentList.value[0].content += content
        }
      } else {
        contentList.value[0].content += content
      }
    }
    streamLoading.value = false
    database.addData('contents', contentList.value[1]).then(() => {
      database.addData('contents', contentList.value[0])
    })
  }).catch((e: any) => {
    loading.value = false
    streamLoading.value = false
    contentList.value[0].role = 'error'
    contentList.value[0].content = e.message || '请求失败！'
    database.addData('contents', contentList.value[1]).then(() => {
      database.addData('contents', contentList.value[0])
    })
  })
}

// 第一次
function onFocus() {
  if (!chatStore.currentChat.model) {
    emitter.emit('chat/edit', { type: 'chat' })
  }
}
</script>
<style lang="less">
.page-chat {
  display: flex;
  flex-direction: column;

  .chat-main {
    flex: 1;
    overflow: auto;
    padding: 20px;
  }

  .chat-header {
    height: 50px;
    background-color: #343541;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 10px;

    .chat-name {
      .ellipsis(1);
    }
  }

  .chat-footer {
    background-color: #343541;
    padding: 20px;
  }

  .thinked {
    .t-icon {
      color: var(--td-success-color-5);
      font-size: 17px;
      margin-right: 5px;
    }
  }
}
</style>
